package xyz.lwm.lazycat.beans;

import lombok.AllArgsConstructor;
import xyz.lwm.lazycat.annotation.BeanScan;
import xyz.lwm.lazycat.utility.CollectionUtil;
import xyz.lwm.lazycat.utility.It;
import xyz.lwm.lazycat.utility.StrPool;
import xyz.lwm.lazycat.utility.exception.LazycatException;
import xyz.lwm.lazycat.utility.reflect.ClassUtil;

/**
 * 启动类处理
 *
 * @author lwm
 */
@AllArgsConstructor
class BeanDesignStartupLoader implements BeanDesignRegistryCustomizer {

    private static final String JAVA_COMMAND  = "sun.java.command";

    private static final String JAR_SUBFIX  = ".jar";

    private final BeanDesignRegistryCustomizers registryCustomizers;

    @Override
    public void customize(BeanDesignRegistry beanRegistry) {

        String startupClass = getStartupClass();
        try {
            Class<?> mainClazz = ClassUtil
                    .getDefaultClassLoader()
                    .loadClass(startupClass);
            register(mainClazz, beanRegistry);
        } catch (ClassNotFoundException e) {
            throw new LazycatException(e);
        }

    }

    // 注册启动类
    private void register(Class<?> clz, BeanDesignRegistry beanRegistry) {
        // 注册启动类; 同时启动类也是配置类, 按配置类处理
        BeanDesignUtil.buildDesign(clz).also(beanRegistry::register)
                .also(design ->
                        registryCustomizers.add(new BeanDesignConfigurationLoader(design, registryCustomizers)))
                // 启动类有 @BeanScan 注解时, 在 BeanDesignConfigurationLoader 中会处理
                // 启动类没有 @BeanScan 注解时, 则默认指定当前包名并使用 BeanDesignScanLoader 扫描加载
                .let(design -> design.getAnnotations().getAnnotation(BeanScan.class))
                .let(BeanScan::value).filter(CollectionUtil::isEmpty).orElse(new String[]{clz.getPackage().getName()})
                .also(pkgs -> registryCustomizers.add(new BeanDesignScanLoader(pkgs, registryCustomizers)));
    }

    // 获取启动类
    private String getStartupClass() {
        return It.of(System.getProperty(JAVA_COMMAND)).let(cmd -> {
            String[] args = cmd.split(StrPool.STR_SPACE);
            if (CollectionUtil.isNotEmpty(args)) {
                for (String arg : args) {
                    int i = arg.indexOf(StrPool.STR_EQUAL);
                    if (i == -1 && !arg.startsWith(StrPool.STR_MINUS) &&
                            !arg.endsWith(JAR_SUBFIX)) {
                        return arg;
                    }
                }
            }
            return null;
        }).getOrThrow(() -> new RuntimeException("startup class not found"));
    }

}
